package top.ochiamalu.aioj.oauth.platform.impl;

import com.google.gson.JsonObject;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import org.springframework.stereotype.Component;
import top.ochiamalu.aioj.common.ErrorCode;
import top.ochiamalu.aioj.converter.UserConverters;
import top.ochiamalu.aioj.domain.dto.oauth.OAuthUserDTO;
import top.ochiamalu.aioj.domain.entity.OAuth;
import top.ochiamalu.aioj.domain.entity.User;
import top.ochiamalu.aioj.domain.vo.user.UserLoginVO;
import top.ochiamalu.aioj.enums.OAuthTypeEnum;
import top.ochiamalu.aioj.exception.BusinessException;
import top.ochiamalu.aioj.oauth.platform.OAuthPlatform;
import top.ochiamalu.aioj.properties.GiteeProperties;
import top.ochiamalu.aioj.service.OAuthService;
import top.ochiamalu.aioj.service.UserService;
import top.ochiamalu.aioj.util.OAuthUtils;

import javax.annotation.Resource;
import java.io.IOException;

/**
 * gitee平台
 *
 * @author ochiamalu
 * @date 2025/03/12
 */
@Component("giteePlatform")
public class GiteePlatform implements OAuthPlatform {

    @Resource
    private GiteeProperties giteeProperties;

    @Resource
    private OAuthUtils oAuthUtils;

    @Resource
    private OAuthService oAuthService;

    @Resource
    private UserService userService;

    private static final String ACCESS_TOKEN_URL = "https://gitee.com/oauth/token";

    private static final String USER_INFO_URL = "https://gitee.com/api/v5/user";

    @Override
    public OAuthUserDTO getUser(String code) throws IOException {
        String accessToken = getAccessToken(code);
        if (accessToken == null) {
            return null;
        }

        Request request = new Request.Builder()
                .url(USER_INFO_URL + "?access_token=" + accessToken)
                .get()
                .build();

        String response = oAuthUtils.executeRequest(request);
        if (response != null) {
            JsonObject userJson = oAuthUtils.getGson().fromJson(response, JsonObject.class);
            return new OAuthUserDTO()
                    .setLogin(userJson.get("login").getAsString())
                    .setId(userJson.get("id").getAsString());
        }
        return null;
    }

    @Override
    public UserLoginVO auth(String code) throws IOException {
        OAuthUserDTO user = getUser(code);
        if (user != null) {
            OAuth oAuth = oAuthService.getByTypeAndOpenId(OAuthTypeEnum.GITEE, user.getId());
            if (oAuth != null) {
                User dbUser = userService.getById(oAuth.getUserId());
                return UserConverters.INSTANCE.convertEntity2LoginVO(dbUser);
            }
        }
        return null;
    }

    @Override
    public UserLoginVO bind(Long userId, OAuthUserDTO userInfo) {
        OAuth existingOAuth = oAuthService.getByTypeAndOpenId(OAuthTypeEnum.GITEE, userInfo.getId());
        if (existingOAuth != null) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "该 Gitee 账号已被其他用户绑定");
        }
        oAuthService.save(
                OAuth.builder()
                .userId(userId)
                .loginType(OAuthTypeEnum.GITEE.getValue())
                .openId(Long.parseLong(userInfo.getId()))
                .username(userInfo.getLogin())
                .build());
        return UserConverters.INSTANCE.convertEntity2LoginVO(userService.getById(userId));
    }

    @Override
    public boolean isBound(Long userId) {
        return oAuthService.lambdaQuery()
                .eq(OAuth::getUserId, userId)
                .eq(OAuth::getLoginType, OAuthTypeEnum.GITEE.getValue())
                .count() > 0;
    }

    @Override
    public boolean unbind(Long userId) {
        return oAuthService.lambdaUpdate()
                .eq(OAuth::getUserId, userId)
                .eq(OAuth::getLoginType, OAuthTypeEnum.GITEE.getValue())
                .remove();
    }

    private String getAccessToken(String code) throws IOException {
        JsonObject messageObj = new JsonObject();
        messageObj.addProperty("grant_type", "authorization_code");
        messageObj.addProperty("code", code);
        messageObj.addProperty("client_id", giteeProperties.getClientId());
        messageObj.addProperty("client_secret", giteeProperties.getClientSecret());
        messageObj.addProperty("redirect_uri", giteeProperties.getRedirectUri());

        MediaType jsonType = MediaType.parse("application/json; charset=utf-8");
        RequestBody body = RequestBody.create(oAuthUtils.getGson().toJson(messageObj), jsonType);

        Request request = new Request.Builder()
                .url(ACCESS_TOKEN_URL)
                .addHeader("Content-Type", "application/json")
                .addHeader("Accept", "application/json")
                .post(body)
                .build();

        String response = oAuthUtils.executeRequest(request);
        if (response != null) {
            JsonObject jsonObject = oAuthUtils.getGson().fromJson(response, JsonObject.class);
            return jsonObject.get("access_token").getAsString();
        }
        return null;
    }
} 